#ifndef _CCAPSULE2D_H_
#define _CCAPSULE2D_H_

#include "StdDefs.h"
#include "CMathFixed.h"
#include "CVector2d.h"
#include "CLineSegment2d.h"
#include "CSpace.h"
#include "CPlane.h"
#include "CCircle.h"

class CCapsule2d
{
public:
	CCapsule2d();
	CCapsule2d( fixed radius, const CLineSegment2d& cylindricalSegment );

	static boolean			Sweep( const CVector2d& c0v0, const CVector2d& c0v1, fixed r1, 
								   const CVector2d& c1v0, const CVector2d& c1v1, fixed r2,
								   const CVector2d& v1, const CVector2d& v2, fixed timeElapsed, fixed& t );

	static boolean			Sweep( const CVector2d& c0v0, const CVector2d& c0v1, fixed r1, 
								   const CVector2d& pos, fixed r2,
								   const CVector2d& v1, const CVector2d& v2, fixed& t );

	static boolean			Intersects( const CVector2d& c0v0, const CVector2d& c0v1, fixed r1, 
										const CVector2d& c1v0, const CVector2d& c1v1, fixed r2 );

	static boolean			Intersects( const CVector2d& c0v0, const CVector2d& c0v1, fixed r1, 
										const CPlane& plane );

	static boolean			Intersects( const CVector2d& c0v0, const CVector2d& c0v1, fixed r1, 
										const CVector2d& pos, fixed r2 );

	boolean					Sweep( const CCapsule2d& c, const CVector2d& v1, const CVector2d& v2, fixed timeElapsed, fixed& u ) const;
	boolean					Sweep ( const CCircle& circle, const CVector2d& v1, const CVector2d& v2, fixed timeElapsed, fixed& u ) const;
	boolean					Intersects( const CCapsule2d &c ) const;
	boolean					Intersects( const CPlane& plane ) const;
	boolean					Intersects( const CCircle& circle ) const;

	const CLineSegment2d&	GetCylindricalSegment() const;
	const fixed&			GetRadius() const;

private:
	fixed					m_radius;
	CLineSegment2d			m_seg;
};


inline
boolean CCapsule2d::Intersects( const CVector2d& c0v0, const CVector2d& c0v1, fixed r1, 
							  const CVector2d& c1v0, const CVector2d& c1v1, fixed r2 )
{
	CVector2d c1, c2;
	CLineSegment2d::ShortestVectorToSegment( c0v0, c0v1, c1v0, c1v1, c1, c2 );
	c1 -= c2;
	r1 += r2;
	if ( c1 * c1 < CMathFixed::Mul( r1, r1 ) )
		return TRUE;

	return FALSE;
}



inline
boolean CCapsule2d::Sweep( const CCapsule2d& c, const CVector2d& v1, const CVector2d& v2, fixed timeElapsed, fixed& t ) const
{
	return Sweep( m_seg.m_v0, m_seg.m_v1, m_radius, c.GetCylindricalSegment().m_v0, c.GetCylindricalSegment().m_v1, c.GetRadius(), v1, v2, timeElapsed, t );
}


inline
boolean CCapsule2d::Sweep( const CCircle& circle, const CVector2d& v1, const CVector2d& v2, fixed timeElapsed, fixed& t ) const
{
	return Sweep( m_seg.m_v0, m_seg.m_v1, m_radius, circle.m_translation, circle.m_radius, v1, v2, t );
}


inline
boolean CCapsule2d::Intersects( const CCapsule2d &c ) const
{
	return Intersects( m_seg.m_v0, m_seg.m_v1, m_radius, c.GetCylindricalSegment().m_v0, c.GetCylindricalSegment().m_v1, c.GetRadius() );
}


inline
boolean CCapsule2d::Intersects( const CPlane &plane ) const
{
	return Intersects( m_seg.m_v0, m_seg.m_v1, m_radius, plane );
}


inline
boolean CCapsule2d::Intersects( const CCircle &circle ) const
{
	return Intersects( m_seg.m_v0, m_seg.m_v1, m_radius, circle.m_translation, circle.m_radius );
}


inline
const CLineSegment2d& CCapsule2d::GetCylindricalSegment() const
{
	return m_seg;
}


inline
const fixed& CCapsule2d::GetRadius() const
{
	return m_radius;
}

#endif //_CCAPSULE2D_H_